<script setup lang="ts">
import { ref, onMounted } from "vue";
// @ts-ignore
import Geo from "../tools/Poly/Geo.js";// @ts-ignore
import Mat from "../tools/Poly/Mat.js";// @ts-ignore
import Obj3D from "../tools/Poly/Obj3D.js";// @ts-ignore
import Scene from "../tools/Poly/Scene.js";// @ts-ignore
import Frame from "../tools/Poly/Frame.js";// @ts-ignore
import { CreateProgram } from "../tools/Utils.js";
import { LS_BackChange, LS_View } from "../tools/shaderTool.ts";
import { Matrix4, Vector3 } from 'three';
import ImageMananger from '../manager/imageManager'
import resizeManager from '../manager/resizeManager'


interface configData {
    jumpTime: number,//跳转时间间隔
    disaTime: number,//消失时间
    disaState: number,//消失状态
    switchTime: number,//切换时间
    switchState: number,//切换状态
    imageSize: number,//图片质量(2的幂数)
}

interface webGLData {
    gl?: any,
    backObj?: Obj3D,
    view?: Obj3D,
    scene?: Scene,
    frame?: Frame,
    eye?: Vector3,
    lookAt?: Vector3,
    pvM4?: Matrix4,
}

const config: configData = {
    jumpTime: 10000,//跳转时间间隔
    disaTime: 1000,//消失时间
    disaState: 0,//(目前无用)
    switchTime: 1500,//跳转时间
    switchState: 0,//切换状态
    imageSize: 2048,
};
const canvas = ref<HTMLCanvasElement>();
const webGL: webGLData = {};

const emit = defineEmits(["isShow", 'delbackDiv']);


onMounted(async () => {
    main();

})

let imageIndex = 0;
const imageArr: Array<HTMLImageElement> = [];
const textureArr: Array<HTMLImageElement> = [];
let lastLoadTime = 99999999;
let curSet = 0;
let curSetOfExit = 0;
let timestamp = 0;
let isSwitch = false;
let isExit = false;
let isEnter = true;

const main = async () => {


    const canvasDom = canvas.value!;
    canvasDom.width = window.innerWidth;
    canvasDom.height = window.innerHeight;

    const gl = createGL();
    gl.viewport(0, 0, canvasDom.width, canvasDom.height);
    gl.clearColor(0.0, 0.0, 0.0, 0.0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    const scene = new Scene({ gl: gl });
    const frame = new Frame({ gl: gl, width: config.imageSize, height: config.imageSize });

    await LS_BackChange(frame);
    await LS_View(scene);


    const eye = new Vector3(0, 0, 3);
    const lookAt = new Vector3();
    const pvM4 = setPvM4(eye, lookAt);

    const image = (await ImageMananger.getRandomImage('back'))!;
    const image1 = (await ImageMananger.getNextImage('back', image))!;
    const texture_01 = (await ImageMananger.get('texture', '01'))!;
    imageIndex++;
    imageArr.push(image);
    imageArr.push(image1);
    textureArr.push(texture_01);

    const [w, h] = [16 / 9, 1];
    const obj = new Obj3D({
        geo: new Geo({
            data: {
                'a_Position': { size: 3, array: new Float32Array([-w, h, 0, -w, -h, 0, w, -h, 0, w, h, 0]) },
                'a_Pin': { size: 2, array: new Float32Array([0, 1, 0, 0, 1, 0, 1, 1,]) }
            },
            element: { array: new Uint16Array([0, 1, 2, 0, 2, 3]) }
        }),
        mat: new Mat({
            program: 'backChange',
            mode: ['TRIANGLES', 'POINTS'],
            data: {
                'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                'u_ModelM4': { type: 'uniformMatrix4fv', value: new Matrix4().elements },
                'u_Set': { type: 'uniform2fv', value: [100, 0] },
            },
            maps: {
                'u_Sampler1': {
                    image: image,
                    WRAP_W: gl.CLAMP_TO_EDGE,
                    WRAP_H: gl.CLAMP_TO_EDGE,
                    MIN_FILTER: gl.LINEAR,
                },
                'u_Sampler2': {
                    image: image1,
                    WRAP_W: gl.CLAMP_TO_EDGE,
                    WRAP_H: gl.CLAMP_TO_EDGE,
                    MIN_FILTER: gl.LINEAR,
                },
                'u_texture': {
                    image: texture_01,
                    WRAP_W: gl.CLAMP_TO_EDGE,
                    WRAP_H: gl.CLAMP_TO_EDGE,
                    MIN_FILTER: gl.LINEAR,
                },
            }
        })
    });
    frame.add(obj);


    const view = new Obj3D({
        geo: new Geo({
            data: {
                'a_Position': {
                    size: 3, array: new Float32Array([-1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0,])
                },
                'a_Pin': { size: 2, array: new Float32Array([0, 1, 0, 0, 1, 0, 1, 1]) },
            },
            element: { array: new Uint16Array([0, 1, 2, 0, 2, 3]) }
        }),
        mat: new Mat({
            program: 'view',
            mode: ['TRIANGLES'],
            data: {
                'u_PvM4': { type: 'uniformMatrix4fv', value: new Matrix4().elements },
                'u_ModelM4': { type: 'uniformMatrix4fv', value: new Matrix4().elements },
                'u_Set': { type: 'uniform2fv', value: [100, 0] },
            },
        })
    });
    scene.add(view);

    webGL.backObj = obj;
    webGL.view = view;
    webGL.gl = gl;
    webGL.scene = scene;
    webGL.frame = frame;
    webGL.pvM4 = pvM4;
    webGL.eye = eye;
    webGL.lookAt = lookAt;

    resizeManager.add('canvasBackground', windowResize);
    // window.onresize = windowResize;
    canvas.value!.onclick = canvasClick;
    windowResize();

    init();
    ani(performance.now());
}

const createGL = () => {
    const gl = canvas.value!.getContext("webgl", { antialias: true, })!;
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
    gl.enable(gl.DEPTH_TEST);
    return gl;
}

const setPvM4 = (eye: Vector3, lookAt: Vector3) => {
    const eyem = new Matrix4().setPosition(eye.x, eye.y, eye.z);
    const lookAtm = new Matrix4().lookAt(
        eye, lookAt, new Vector3(0, 1, 0)
    );
    const viewm = (eyem.multiply(lookAtm)).invert();

    const viewH = 1;//设定视图矩阵高度  
    const wh = canvas.value!.width / canvas.value!.height;
    const viewW = viewH * wh;//求视图矩阵宽度  
    const [l, r, t, b, q, h] = [
        -viewW, viewW, viewH, -viewH, 1, 20
    ];
    const projectionm = new Matrix4().makeOrthographic(l, r, t, b, q, h);
    return new Matrix4().copy(projectionm.multiply(viewm));
}

const windowResize = () => {
    const { eye, lookAt } = webGL;
    const canvasDom = canvas.value!;

    const windowWH = window.innerWidth / window.innerHeight;
    const WH = 16 / 9;
    if (windowWH < WH) {
        //太高,高为1
        canvasDom.height = window.innerHeight;
        canvasDom.width = WH * window.innerHeight;

        canvasDom.style.left = -(canvasDom.width - window.innerWidth) / 2 + 'px';
        canvasDom.style.top = '0px';
    } else {
        //太宽,宽为1
        canvasDom.width = window.innerWidth;
        canvasDom.height = window.innerWidth / WH;
        canvasDom.style.top = -(canvasDom.height - window.innerHeight) / 2 + 'px';
        canvasDom.style.left = '0px';
    }

    const pvM4 = setPvM4(eye!, lookAt!);
    webGL.pvM4 = pvM4;
}

const switchImage = async () => {
    const { gl, backObj } = webGL;
    const image = (await ImageMananger.getNextImage('back', backObj.mat.maps['u_Sampler2'].image))!;
    imageArr[0] = imageArr[1];
    imageArr[1] = image;

    //加载第二张
    backObj.setMap('u_Sampler1', {
        image: imageArr[0],
        WRAP_W: gl.CLAMP_TO_EDGE,
        WRAP_H: gl.CLAMP_TO_EDGE,
        MIN_FILTER: gl.LINEAR,
    });
    backObj.setMap('u_Sampler2', {
        image: imageArr[1],
        WRAP_W: gl.CLAMP_TO_EDGE,
        WRAP_H: gl.CLAMP_TO_EDGE,
        MIN_FILTER: gl.LINEAR,
    });
    curSet = timestamp;
    isSwitch = true;
    windowResize();
}

const canvasClick = () => {
    if (!isExit) {
        isExit = true;
        curSetOfExit = timestamp;
    }
}

const delCanvasCom = () => {
    emit('isShow', false);
}

const init = () => {
    lastLoadTime = 99999999;
    curSet = performance.now();
    curSetOfExit = performance.now();
    timestamp = performance.now();
    isSwitch = false;
    isExit = false;
    isEnter = true;
}


const ani = function (time: number) {
    const { scene, frame, pvM4, backObj, gl, view } = webGL;
    const { jumpTime, disaTime, switchTime, switchState } = config;
    //#region 控制切换
    if (time > lastLoadTime) {
        lastLoadTime += jumpTime;
        switchImage();
    }
    if (isSwitch) {
        const cur = (time - curSet) / switchTime;
        backObj.setUniform('u_Set', { value: [cur, switchState] });
        if (cur > 1.2) {
            // 卸载
            isSwitch = false;
        }
    }
    //#endregion

    //#region 开始显示
    if (isEnter) {
        const cur = (time - curSetOfExit) / disaTime;
        view.setUniform('u_Set', { value: [cur, 0] });
        if (cur > 1.2) {
            isEnter = false;
            lastLoadTime = config.switchTime + time;
        }
    }
    if (isExit) {
        isEnter = false;
        const cur = (time - curSetOfExit) / disaTime;
        view.setUniform('u_Set', { value: [cur, 1] });
        if (cur > 1.2) {
            delCanvasCom();
            isExit = false;
            return;
        }
    }
    //#endregion

    frame.setUniform('u_PvM4', { value: pvM4!.elements });
    const texure = frame.draw();
    view.addTexureNew(gl, { 'u_ViewTexture': { texture: texure } });
    scene.draw([0, 0, 0, 0]);

    requestAnimationFrame(ani);
    timestamp = time;
}




</script>


<template>
    <canvas ref="canvas" class="canvas"></canvas>
</template>

<style scoped>
.canvas {
    position: fixed;
    top: 0px;
    left: 0px;
    /* background-color: aqua; */
    z-index: 99999;
}
</style>